
// SingleNodeSimulatorDlg.cpp : implementation file
//

#include "stdafx.h"
#include "SingleNodeSimulator.h"
#include "SingleNodeSimulatorDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	enum { IDD = IDD_ABOUTBOX };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support

// Implementation
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()


// CSingleNodeSimulatorDlg dialog




CSingleNodeSimulatorDlg::CSingleNodeSimulatorDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CSingleNodeSimulatorDlg::IDD, pParent)
	, m_nDataNumber(20000)
	, m_nPivotNumber(8)
	, m_nStep(1000)
	, m_nSimpleNumber(200)
#ifdef USE_VECTOR
	, m_nMaxDis(620)
#else
#ifdef USE_NIL
	, m_nMaxDis(128)
#endif
#endif
	, m_nPlotType (MeanOnly)
	, m_nRepeatTimes(10)
	, m_nStartK(50)
	, m_nStopK(500)
	, m_nDivide(9)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CSingleNodeSimulatorDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Text(pDX, IDC_EDIT2, m_nDataNumber);
	DDX_Text(pDX, IDC_EDIT3, m_nPivotNumber);
	DDV_MinMaxUInt(pDX, m_nPivotNumber, 1, 1000);
	DDX_Text(pDX, IDC_EDIT4, m_nStep);
	DDV_MinMaxUInt(pDX, m_nStep, 1, 20000);
	DDX_Text(pDX, IDC_EDIT5, m_nSimpleNumber);
	DDV_MinMaxUInt(pDX, m_nSimpleNumber, 5, 1000);
	DDX_Text(pDX, IDC_EDIT6, m_nMaxDis);
	DDX_Text(pDX, IDC_EDIT7, m_nRepeatTimes);
	DDX_Text(pDX, IDC_EDIT10, m_nStartK);
	DDX_Text(pDX, IDC_EDIT8, m_nStopK);
	DDX_Text(pDX, IDC_EDIT9, m_nDivide);
}

BEGIN_MESSAGE_MAP(CSingleNodeSimulatorDlg, CDialog)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	//}}AFX_MSG_MAP
	ON_BN_CLICKED(IDC_BUTTON_IMPORT_DATA, &CSingleNodeSimulatorDlg::OnBnClickedButtonImportData)
	ON_BN_CLICKED(IDC_BUTTON_RUN, &CSingleNodeSimulatorDlg::OnBnClickedButtonRun)
	ON_BN_CLICKED(IDC_BUTTON_GET_RES, &CSingleNodeSimulatorDlg::OnBnClickedButtonGetRes)
	ON_BN_CLICKED(IDC_BUTTON_GET_RES2, &CSingleNodeSimulatorDlg::OnBnClickedButtonGetRes2)
	ON_BN_CLICKED(IDC_RADIO1, &CSingleNodeSimulatorDlg::OnBnClickedRadio1)
	ON_BN_CLICKED(IDC_RADIO2, &CSingleNodeSimulatorDlg::OnBnClickedRadio2)
	ON_BN_CLICKED(IDC_RADIO3, &CSingleNodeSimulatorDlg::OnBnClickedRadio3)
	ON_BN_CLICKED(IDC_BUTTON_RUN_KNN, &CSingleNodeSimulatorDlg::OnBnClickedButtonRunKnn)
END_MESSAGE_MAP()


// CSingleNodeSimulatorDlg message handlers

BOOL CSingleNodeSimulatorDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon

	// TODO: Add extra initialization here
#ifdef _DEBUG
	srand(12345);
#else
	srand(GetTickCount());
#endif
	((CButton *)GetDlgItem(IDC_RADIO1))->SetCheck(TRUE);
	
#ifdef USE_VECTOR
	this->SetWindowTextA("for Vector Data Files ");
#else
	#ifdef USE_NIL
	this->SetWindowTextA("for Nilsimsa Key Files  ");
	#endif
#endif
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CSingleNodeSimulatorDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CSingleNodeSimulatorDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this function to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CSingleNodeSimulatorDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}



void CSingleNodeSimulatorDlg::OnBnClickedButtonImportData()
{
	// TODO: Add your control notification handler code here
	this->UpdateData();
#ifdef USE_VECTOR
	CFileDialog cFile(TRUE,"asc",NULL,6,"Vector Data Files (*.asc)|*.asc||");
#else
	#ifdef USE_NIL
	CFileDialog cFile(TRUE,"","Data.nil",6,"Nilsimsa Key Files (*.nil)|*.nil||");
	#endif
#endif
	if(cFile.DoModal()==IDOK)
	{
		ifstream fin(cFile.GetPathName().GetString());
		if(fin)
		{
			m_cKeyVector.clear();
			char Buffer[1024];
			while(fin.getline(Buffer,1024))
			{
				KEY tmp;
				if(tmp.FromString(Buffer))
				{
					m_cKeyVector.push_back(tmp);
				}
				if(m_cKeyVector.size()==m_nDataNumber)
				{
					break;
				}
			}
			if(m_cKeyVector.size()==m_nDataNumber)
			{
				this->MessageBox("Success");
				GetDlgItem(IDC_BUTTON_RUN)->EnableWindow();
				
				GetDlgItem(IDC_BUTTON_IMPORT_DATA)->EnableWindow(FALSE);
				return ;
			}
			else
			{
				this->MessageBox("raw data not enough.");
			}
		}
		else
		{
			this->MessageBox("Open file error.");
		}
	}
}

void CSingleNodeSimulatorDlg::OnBnClickedButtonRun()
{
	// TODO: Add your control notification handler code here
	this->UpdateData();
	m_cCalculator[0].clear();
	m_cCalculator[1].clear();
	DWORD nGroupsNo = pow(2,m_nPivotNumber);
	vector<KEY> cPivotList;
	vector<vector<int>> cDisTable(m_nPivotNumber+1,vector<int>(m_nPivotNumber+2,0));
	for(DWORD nInserted = 0;nInserted<this->m_nDataNumber;++nInserted)
	{
		if(cPivotList.size()<1+m_nPivotNumber)
		{
			cPivotList.push_back(m_cKeyVector[nInserted]);
			if(cPivotList.size()==1+m_nPivotNumber)
			{
				for(DWORD i = 0;i<m_nPivotNumber+1; ++i)
				{
					for(DWORD j =i+1;j<m_nPivotNumber+1;j++)
					{
						cDisTable[i][j] = cDisTable[j][i]= KEY::GetDistance(cPivotList[i],cPivotList[j]);
						cDisTable[i][m_nPivotNumber+1] += cDisTable[i][j] ;
						cDisTable[j][m_nPivotNumber+1] += cDisTable[j][i];
					}
				}
				int nMinIndex = 0;
				int nMin = cDisTable[nMinIndex][m_nPivotNumber+1];
				for(DWORD i = 0;i<m_nPivotNumber+1;i++)
				{
					if(cDisTable[i][m_nPivotNumber+1]<nMin)
					{
						nMinIndex = i;
						nMin = cDisTable[i][m_nPivotNumber+1];
					}
				}
				if(nMin!=m_nPivotNumber)
				{
					swap(cDisTable[m_nPivotNumber],cDisTable[nMinIndex]);
					for(DWORD i = 0;i<m_nPivotNumber;i++)
					{
						swap(cDisTable[i][m_nPivotNumber],cDisTable[i][nMinIndex]);
					}
				}
			}
		}
		else
		{
			cPivotList[m_nPivotNumber] = m_cKeyVector[nInserted];
			cDisTable[m_nPivotNumber][m_nPivotNumber] = 0;
			for(DWORD i = 0;i<m_nPivotNumber; ++i)
			{
				cDisTable[i][m_nPivotNumber] = cDisTable[m_nPivotNumber][i]=KEY::GetDistance(cPivotList[i],cPivotList[m_nPivotNumber]);
			}
			int nMinIndex = 0;
			int nMin = cDisTable[nMinIndex][m_nPivotNumber+1];
			for(DWORD i = 0;i<m_nPivotNumber+1;i++)
			{
				if(cDisTable[i][m_nPivotNumber+1]<nMin)
				{
					nMinIndex = i;
					nMin = cDisTable[i][m_nPivotNumber+1];
				}
			}
			if(nMin!=m_nPivotNumber)
			{
				swap(cDisTable[m_nPivotNumber],cDisTable[nMinIndex]);
				for(DWORD i = 0;i<m_nPivotNumber;i++)
				{
					swap(cDisTable[i][m_nPivotNumber],cDisTable[i][nMinIndex]);
				}
			}
		}
		if(nInserted>=m_nStep&&nInserted%m_nStep+1==m_nStep)
		{
			m_cCalculator[0].push_back(CCalculator());
			m_cCalculator[1].push_back(CCalculator());
			map<DWORD,vector<KEY>> cClustedData;
			for(DWORD i = 0;i<=nInserted;i++)
			{
				DWORD nIndex = 0;
				for(DWORD j =0;j<m_nPivotNumber;j++)
				{
					if(KEY::GetDistance(cPivotList[j],m_cKeyVector[i])>m_nMaxDis)
					{
						nIndex+=pow(2,j);
					}
				}
				assert(nIndex<nGroupsNo);
				map<DWORD,vector<KEY>>::iterator it = cClustedData.find(nIndex);
				if(it==cClustedData.end())
				{
					it = cClustedData.insert(make_pair(nIndex,vector<KEY>())).first;
				}
				it->second.push_back(m_cKeyVector[i]);
			}
			for(DWORD i = 0;i<m_nSimpleNumber;i++)
			{
				map<DWORD,vector<KEY>>::iterator it=cClustedData.lower_bound(rand_range(cClustedData.begin()->first,cClustedData.rbegin()->first));
				while(it->second.size()<2)
				{
					++it;
					if(it==cClustedData.end())
					{
						it = cClustedData.begin();
					}
				}
				int nPos1 = rand()%it->second.size();
				int nPos2 = rand()%it->second.size();
				if(nPos2>=nPos1)
				{
					nPos2++;
					nPos2%=it->second.size();
				}
				m_cCalculator[0].rbegin()->Add(KEY::GetDistance(it->second[nPos1],it->second[nPos2]));
				nPos1 = rand()%nInserted;
				nPos2 = rand()%nInserted;
				if(nPos2>=nPos1)
				{
					nPos2++;
					nPos2%=nInserted;
				}
				m_cCalculator[1].rbegin()->Add(KEY::GetDistance(m_cKeyVector[nPos1],m_cKeyVector[nPos2]));

			}
			m_cCalculator[0].rbegin()->Calculate();
			m_cCalculator[1].rbegin()->Calculate();
			if(m_nDataNumber-m_nStep<=nInserted)
			{
				m_cFinalClustedData.swap(cClustedData);
				m_cFinalPivotList.swap(cPivotList);
			}
		}
	}
	this->MessageBox("Success");
	GetDlgItem(IDC_BUTTON_GET_RES)->EnableWindow();
	GetDlgItem(IDC_BUTTON_RUN_KNN)->EnableWindow();
}

void CSingleNodeSimulatorDlg::OnBnClickedButtonGetRes()
{
	// TODO: Add your control notification handler code here
	CString strName;
	switch(m_nPlotType)
	{
		case StdDevi:
		{
			strName = "Data_Clusted_SD.eps";
		}
		break;
		case MaxMin:
		{
			strName = "Data_Clusted_MM.eps";
		}
		break;
		default:
		{
			strName = "Data_Clusted.eps";
		}
		break;
	};
	CFileDialog cFile(FALSE,"eps",strName,6,"EPS Files (*.eps)|*.eps||");
	if(cFile.DoModal()==IDOK)
	{
		CString strFigureNamePath(cFile.GetPathName());
		CString strRawDataNamePath(strFigureNamePath);
		strRawDataNamePath=strRawDataNamePath.Left(strRawDataNamePath.ReverseFind('.'));
		strRawDataNamePath.Append(".dat");
		CString strScriptNamePath(strFigureNamePath.Left(strFigureNamePath.ReverseFind('.')));
		strScriptNamePath.Append(".plt");
		ofstream fout(strRawDataNamePath.GetString());
		if(fout)
		{
			for (unsigned i = 0;i<m_cCalculator[0].size();i++)
			{
				fout<<m_nStep*(i+1)
					<<" "<<m_cCalculator[0][i].GetEven()
					<<" "<<m_cCalculator[0][i].GetEven()-m_cCalculator[0][i].GetSDev()
					<<" "<<m_cCalculator[0][i].GetEven()+m_cCalculator[0][i].GetSDev()
					<<" "<<m_cCalculator[0][i].GetMin()
					<<" "<<m_cCalculator[0][i].GetMax()
					<<" "<<m_cCalculator[1][i].GetEven()
					<<" "<<m_cCalculator[1][i].GetEven()-m_cCalculator[1][i].GetSDev()
					<<" "<<m_cCalculator[1][i].GetEven()+m_cCalculator[1][i].GetSDev()
					<<" "<<m_cCalculator[1][i].GetMin()
					<<" "<<m_cCalculator[1][i].GetMax()<<endl;	
			}
			fout.close();
		}
		else
		{
			this->MessageBox("Create Data File Error!");
			return ;
		}
		CString script("reset \n");
		script.AppendFormat("set term postscript eps color enhanced \n");
		script.AppendFormat("set output '%s'\n",strFigureNamePath.GetString());
		script.AppendFormat("set title 'Distance Distribution Contrast'\n");
		script.AppendFormat("set key right top\n");
		switch(m_nPlotType)
		{	
			case MaxMin:
			{
				script.AppendFormat("plot '%s' using 1:2:5:6 title 'Clusted' with yerrorbars lt 1 lw 2 ,",strRawDataNamePath.GetString());
				script.AppendFormat("'%s' using 1:7:10:11 title 'Random' with yerrorbars lt 1 lw 2 \n",strRawDataNamePath.GetString());
				break;
			}
			case StdDevi:
			{
				script.AppendFormat("plot '%s' using 1:2:3:4 title 'Clusted' with yerrorbars lt 1 lw 2 ,",strRawDataNamePath.GetString());
				script.AppendFormat("'%s' using 1:7:8:9 title 'Random' with yerrorbars lt 1 lw 2 \n",strRawDataNamePath.GetString());
				break;
			}
			default:
			{
				script.AppendFormat("plot '%s' using 1:2 title 'Clusted' with linespoints lt 1 lw 2 ,'%s' using 1:7 title 'Random'  with linespoints lt 2 lw 2 \n\n",strRawDataNamePath.GetString(),strRawDataNamePath.GetString());
				break;
			}
		}
		script.AppendFormat("set term windows\n");
		script.AppendFormat("replot\n");
		FILE *pFile ;
		if(0==fopen_s(&pFile,strScriptNamePath.GetString(),"w"))
		{
			fwrite(script.GetBuffer(),1,script.GetLength(),pFile);
			fclose(pFile);
			CString cmd;
			cmd.Format("pgnuplot.exe -persist \"%s\"",strScriptNamePath.GetString());
			WinExec(cmd.GetString(),SW_SHOW);
		}
		else
		{
			MessageBox("Open File Error!");
			return ;
		}
	}
}

void CSingleNodeSimulatorDlg::OnBnClickedRadio1()
{
	// TODO: Add your control notification handler code here
	this->m_nPlotType = MeanOnly;
}

void CSingleNodeSimulatorDlg::OnBnClickedRadio2()
{
	// TODO: Add your control notification handler code here
	m_nPlotType =  StdDevi;
}

void CSingleNodeSimulatorDlg::OnBnClickedRadio3()
{
	// TODO: Add your control notification handler code here
	m_nPlotType = MaxMin;
}

void CSingleNodeSimulatorDlg::OnBnClickedButtonRunKnn()
{
	this->UpdateData( );
	vector<CCalculator> cCal(this->m_nDivide+1);
	int nPos = 0 ;
	for(int nRange = m_nStartK;nRange<=m_nStopK;nRange+=(m_nStopK-m_nStartK)/m_nDivide,nPos++)
	{
		for(unsigned nTimes = 0;nTimes<m_nRepeatTimes;nTimes++)
		{	
			// m_cKeyVector[rand()%m_cKeyVector.size()];
			KEY &cSource =m_cFinalPivotList[rand()%m_cFinalPivotList.size()];
			vector <DWORD>  cSortedIndex;
			SortIndex(cSource,cSortedIndex);
			DWORD nIndex = 0;
			for(DWORD j =0;j<m_nPivotNumber;j++)
			{
				if(KEY::GetDistance(m_cFinalPivotList[j],cSource)>m_nMaxDis)
				{
					nIndex+=pow(2,j);
				}
			}
			assert(nIndex==cSortedIndex[0]);
			multimap<int,KEY> cRes;
			int nCurRange = m_nMaxDis;
			int nAccessGroup = 0;
			for(DWORD i = 0;i<cSortedIndex.size();i++)
			{
				if(m_cFinalClustedData.find(cSortedIndex[i])==m_cFinalClustedData.end())
				{
					continue;
				}
				vector<KEY> & cCurGroup = m_cFinalClustedData[cSortedIndex[i]];
				if(cCurGroup.size()==0)
				{
					continue;
				}
				if(Judge(cSortedIndex[i],cSource,nCurRange))
				{
					for(DWORD j = 0;j<cCurGroup.size();j++)
					{
						int nDis = KEY::GetDistance(cSource,cCurGroup[j]);
						if(cRes.size()<(DWORD)nRange)
						{
							cRes.insert(make_pair(nDis,cCurGroup[j]));
						}
						else
						{
							if(nDis<cRes.rbegin()->first)
							{
								cRes.erase(cRes.lower_bound(cRes.rbegin()->first));
								cRes.insert(make_pair(nDis,cCurGroup[j]));
							}
						}
						nCurRange=cRes.rbegin()->first;
					}
					nAccessGroup++;
				}
			}
			cCal[nPos].Add(nAccessGroup);
		}
		cCal[nPos].Calculate( );
	}
	m_cCalculator2.swap(cCal);
	this->MessageBox("Success!");
	GetDlgItem(IDC_BUTTON_GET_RES2)->EnableWindow();
}

bool CSingleNodeSimulatorDlg::Judge(const DWORD dwIndex,const KEY& cKey,const DWORD dwRange)
{
	bool bRes = true;;
	for(unsigned i = 0;i<this->m_nPivotNumber;i++)
	{
		int nDis = KEY::GetDistance(cKey,this->m_cFinalPivotList[i]);
		if((dwIndex&(1<<i))==0)
		{
			if(nDis>(int)dwRange+(int)m_nMaxDis )
			{
				bRes = false;
				break;
			}
		}
		else
		{
			if(nDis<=abs((int)dwRange-(int)m_nMaxDis) )
			{
				bRes = false;
				break;
			}
		}
	}
	return bRes;
}

void CSingleNodeSimulatorDlg::SortIndex(const KEY& cKey, vector <DWORD> & cSortedIndexVector)
{
	vector<int> cPivotPri( m_nPivotNumber,0);
	multimap<int,DWORD> cDistanceSorter;
	for(DWORD i = 0;i<m_nPivotNumber;i++)
	{
		cDistanceSorter.insert(make_pair(abs(m_nMaxDis-KEY::GetDistance(cKey,this->m_cFinalPivotList[i])),i));
	}
	int i = 0;
	for(multimap<int,DWORD>::iterator it = cDistanceSorter.begin();it!=cDistanceSorter.end();++it,++i)
	{
		cPivotPri[it->second] = pow(2,i);
	}
	map<int,DWORD> cSortedIndex;
	for(DWORD index = 0;index<(DWORD )pow(2,m_nPivotNumber);index++)
	{
		int nKey = 0;
		for(DWORD i = 0;i<m_nPivotNumber;i++)
		{
			if((index&(1<<i))==0)
			{
				if(KEY::GetDistance(cKey,m_cFinalPivotList[i])<=m_nMaxDis)
				{
					nKey+=cPivotPri[i];
				}
			}
			else
			{
				if(KEY::GetDistance(cKey,m_cFinalPivotList[i])>m_nMaxDis)
				{
					nKey+=cPivotPri[i];
				}
			}
		}
		cSortedIndex.insert(make_pair(nKey,index));
	}
	cSortedIndexVector.clear();
	for(map<int,DWORD>::reverse_iterator it = cSortedIndex.rbegin();it!=cSortedIndex.rend();++it)
	{
		cSortedIndexVector.push_back(it->second);
	}
}



void CSingleNodeSimulatorDlg::OnBnClickedButtonGetRes2()
{
	// TODO: Add your control notification handler code here
	CString strName;

	CFileDialog cFile(FALSE,"eps","KNN_RESULT.eps",6,"EPS Files (*.eps)|*.eps||");
	if(cFile.DoModal()==IDOK)
	{
		CString strFigureNamePath(cFile.GetPathName());
		CString strRawDataNamePath(strFigureNamePath);
		strRawDataNamePath=strRawDataNamePath.Left(strRawDataNamePath.ReverseFind('.'));
		strRawDataNamePath.Append(".dat");
		CString strScriptNamePath(strFigureNamePath.Left(strFigureNamePath.ReverseFind('.')));
		strScriptNamePath.Append(".plt");
		ofstream fout(strRawDataNamePath.GetString());
		if(fout)
		{
			for (unsigned i = 0;i<m_cCalculator2.size();i++)
			{
				fout<<m_nStartK+(m_nStopK-m_nStartK)*i/m_nDivide
					<<" "<<m_cCalculator2[i].GetEven()
					<<" "<<m_cCalculator2[i].GetEven()-m_cCalculator[0][i].GetSDev()
					<<" "<<m_cCalculator2[i].GetEven()+m_cCalculator[0][i].GetSDev()
					<<" "<<m_cCalculator2[i].GetMin()
					<<" "<<m_cCalculator2[i].GetMax()
					<<endl;	
			}
			fout.close();
		}
		else
		{
			this->MessageBox("Create Data File Error!");
			return ;
		}
		CString script("reset \n");
		script.AppendFormat("set term postscript eps color enhanced \n");
		script.AppendFormat("set output '%s'\n",strFigureNamePath.GetString());
		script.AppendFormat("set title 'kNN Query Result'\n");
		script.AppendFormat("unset key \n");
		switch(m_nPlotType)
		{	
			case MaxMin:
			{
				script.AppendFormat("plot '%s' using 1:2:5:6 with yerrorbars lt 1 lw 1 ,",strRawDataNamePath.GetString());
				script.AppendFormat("'%s' using 1:2 with linespoints lt 1 lw 2 \n",strRawDataNamePath.GetString());
				break;
			}
			case StdDevi:
			{
				script.AppendFormat("plot '%s' using 1:2:3:4 with yerrorbars lt 1 lw 1 ,",strRawDataNamePath.GetString());
				script.AppendFormat("'%s' using 1:2 with linespoints lt 1 lw 2 \n",strRawDataNamePath.GetString());
				break;
			}
			default:
			{
				script.AppendFormat("plot '%s' using 1:2 with linespoints lt 1 lw 2  \n",strRawDataNamePath.GetString() );
				break;
			}
		}
		script.AppendFormat("set term windows\n");
		script.AppendFormat("replot\n");
		FILE *pFile ;
		if(0==fopen_s(&pFile,strScriptNamePath.GetString(),"w"))
		{
			fwrite(script.GetBuffer(),1,script.GetLength(),pFile);
			fclose(pFile);
			CString cmd;
			cmd.Format("pgnuplot.exe -persist \"%s\"",strScriptNamePath.GetString());
			WinExec(cmd.GetString(),SW_SHOW);
		}
		else
		{
			MessageBox("Open File Error!");
			return ;
		}
	}
}
